package com.autonavi.yunda.yunji.core.vo;

import com.autonavi.yunda.yunji.common.exception.AmapException;
import com.autonavi.yunda.yunji.common.exception.AmapExceptionCode;
import com.autonavi.yunda.yunji.common.utils.JsonUtils;
import com.autonavi.yunda.yunji.core.enums.NodeType;
import com.autonavi.yunda.yunji.core.vo.node.BaseNode;
import com.autonavi.yunda.yunji.core.vo.node.EdgeNode;
import com.autonavi.yunda.yunji.core.vo.node.EndNode;
import com.autonavi.yunda.yunji.core.vo.node.StartNode;
import com.autonavi.yunda.yunji.core.vo.param.Param;
import com.fasterxml.jackson.databind.JsonNode;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.autonavi.yunda.yunji.core.vo.node.BaseNode.parseNode;


/**
 * @author cizhong.wcs
 * @date 2022/5/18 17:03
 */
public class EngineData {
    public List<BaseNode> nodes;
    public List<EdgeNode> edges;
    public EngineConfig engineConfig;

    public StartNode fetchStartNode() {
        return nodes.stream().filter(n -> n.nodeType.equals(NodeType.start)).map(n -> (StartNode) n).findFirst()
                .orElseThrow(() -> new AmapException(AmapExceptionCode.COMMON_ILLEGAL_PARAM, "start节点不能为空"));
    }

    public EndNode fetchEndNode() {
        return nodes.stream().filter(n -> n.nodeType.equals(NodeType.end)).map(n -> (EndNode) n).findFirst()
                .orElseThrow(() -> new AmapException(AmapExceptionCode.COMMON_ILLEGAL_PARAM, "end节点不能为空"));
    }

    public EngineData(String jsonConfig) {
        JsonNode json = JsonUtils.from(jsonConfig, JsonNode.class);
        List<BaseNode> nodes = new ArrayList<>();
        List<EdgeNode> edges = new ArrayList<>();
        EngineConfig engineConfig = new EngineConfig();
        if (Objects.isNull(json)) {
            this.nodes = nodes;
            this.edges = edges;
            this.engineConfig = engineConfig;
            return;
        }
        if (!Objects.isNull(json.get("nodes"))) {
            for (JsonNode jsonNode : json.get("nodes")) {
                BaseNode node = parseNode(jsonNode);
                nodes.add(node);
            }
        }
        if (!Objects.isNull(json.get("edges"))) {
            for (JsonNode jsonEdge : json.get("edges")) {
                EdgeNode edge = JsonUtils.from(JsonUtils.toString(jsonEdge), EdgeNode.class);
                edges.add(edge);
            }
        }
        if (!Objects.isNull(json.get("engineConfig"))) {
            engineConfig = JsonUtils.from(JsonUtils.toString(json.get("engineConfig")), EngineConfig.class);
        }
        this.nodes = nodes;
        this.edges = edges;
        this.engineConfig = engineConfig;
    }

    /**
     * 获取整个脚本所有的全局变量名称
     */
    public List<String> fetchAllGlobalVariables() {
        // 开始节点输入的变量
        List<String> varNames = fetchStartNode().inputParams.stream()
                .map(Param::getParamNameInScript).collect(Collectors.toList());
        // 非特殊节点的结果映射字段当做变量
        varNames.addAll(nodes.stream()
                .filter(node -> !node.nodeType.isSpecial())
                .map(node -> node.var).distinct()
                .collect(Collectors.toList()));
        return varNames.stream()
                .filter(varName -> engineConfig.initParams.stream().noneMatch(param -> param.name.equals(varName)))
                .distinct().collect(Collectors.toList());
    }
}
